/*---------- nop ----------*/
action nop() {}

/*---------- forward_t ----------*/
action set_egr(egress_spec) {
  modify_field(ig_intr_md_for_tm.ucast_egress_port, egress_spec);
}

@pragma stage 0
table forward_t {
  reads {
  ig_intr_md.ingress_port: exact;
  }
  actions {
    set_egr; nop;
  }
}
/*---------- set_md_t ----------*/
action set_md_ac() {
  modify_field(md.do_ing_mirroring, 23);
  modify_field(md.do_egr_mirroring, 24);
  modify_field(md.egr_mir_ses, 25);
  modify_field(md.ing_mir_ses, 144);
}

table set_md_t {
  actions {
    set_md_ac;
  }
 default_action: set_md_ac;
}

/*---------- clone_pkt_t ----------*/
field_list clone_fields
{
  md.do_ing_mirroring;
  md.do_egr_mirroring;
  md.ing_mir_ses;
  md.egr_mir_ses;
}

action clone_pkt_ac() {
  /* modify_field(md.ing_mir_ses, 144); */
  clone_ingress_pkt_to_egress(md.ing_mir_ses, clone_fields);
}

table clone_pkt_t {
  actions {
    clone_pkt_ac;
  }
 default_action: clone_pkt_ac;
}

/*---------- count_packet_t ----------*/
blackbox stateful_alu count_packet_bb {
 reg: packet_counter;
 update_lo_1_value: register_lo + 1;
 /* update_lo_1_value: ipv4.srcip; */
}

action count_packet_ac() {
  count_packet_bb.execute_stateful_alu(0);
}

blackbox stateful_alu reg_set_1_bb {
 reg: packet_counter;
 update_lo_1_value: register_lo + 1;
}

action reg_set_1_ac() {
  reg_set_1_bb.execute_stateful_alu(0);
}

blackbox stateful_alu reg_set_2_bb {
 reg: packet_counter;
 /* update_lo_1_value: register_lo + 1; */
 update_lo_1_value: ipv4.srcip;
}

action reg_set_2_ac() {
  reg_set_2_bb.execute_stateful_alu(0);
}

table count_packet_t {
  reads {
  ipv4.srcip: exact;
  }
  actions {
    /* reg_set_1_ac; */
    /* reg_set_2_ac; */
    count_packet_ac;
    nop;
  }
 default_action: nop;
}

/*---------- port_tbl ----------*/
//action add_cpu_header(pad1, fabric_color, fabric_qos, dst_device, dst_port_or_group, reserved1, ingress_ifindex, ingress_bd, reason_code) {
action add_cpu_header() {
    add_header(fabric);
    modify_field(fabric.packetType, FABRIC_HEADER_TYPE_CPU);
    modify_field(fabric.headerVersion, 0);
    modify_field(fabric.packetVersion, 0);
    modify_field(fabric.pad1, 0);
    modify_field(fabric.fabricColor, 0);
    modify_field(fabric.fabricQos, 0);
    modify_field(fabric.dstDevice, 50);
    modify_field(fabric.dstPortOrGroup, 0);
    add_header(fabric_cpu);
    modify_field(fabric_cpu.reserved, 0);
    modify_field(fabric_cpu.ingressIfindex, 0x2223);
    modify_field(fabric_cpu.ingressBd, 0x2425);
    modify_field(fabric_cpu.reasonCode, 0x2627);
    //    modify_field(fabric_header_cpu.ingressPort, ig_intr_md.ingress_port);
    modify_field(fabric_cpu.ingressPort, 0x2021);
    add_header(fabric_payload);
    modify_field(fabric_payload.etherType, ethernet.etherType);
    modify_field(fabric_payload.test, 99);
    modify_field(ethernet.etherType, ETHERTYPE_BF_FABRIC);
    modify_field(ig_intr_md_for_tm.ucast_egress_port, CPU_PORT);
}

table port_tbl {
    reads {
        ig_intr_md.ingress_port : exact;
    }
    actions {
        add_cpu_header;
    }
    default_action: add_cpu_header;
    size : 288;
}

/*---------- fabric_tbl ----------*/
action set_egress_port() {
  //    modify_field(ig_intr_md_for_tm.ucast_egress_port, fabric_header_cpu.ingressPort);
    modify_field(ig_intr_md_for_tm.ucast_egress_port, CPU_PORT);
}

table fabric_tbl {
  //      reads {
  //         ig_intr_md.ingress_port : exact;
  //  }
    actions {
      //  set_egress_port;
      add_cpu_header;
    }
    default_action: add_cpu_header;
    //    size : 288;
}

/*---------- process_ingress_knet ----------*/
control process_ingress_knet {
    if (ig_intr_md.ingress_port != CPU_PORT) {
       apply(port_tbl);
    } else {
       apply(fabric_tbl);
    }
}

/*---------- new_pkt_t ----------*/
action old_pkt() {
    modify_field(fabric.dstDevice, 60);
}

action new_pkt() {
  modify_field(md.new_pkt, 1);
  modify_field(md.ing_mir_ses, 2);
}

table new_pkt_t {
  reads {
  	md.ing_mir_ses: exact;
  }
  actions {
    old_pkt;
    new_pkt;
  }
}

/*---------- pkt_gen_t ----------*/
action pkt_gen() {
  clone_egress_pkt_to_egress(md.ing_mir_ses);
}

table pkt_gen_t {
  reads {
  md.new_pkt: exact;
  }
  actions {
    pkt_gen;
  }
 default_action: pkt_gen;
}

/*---------- pkt_gen_table ----------*/
action pkt_gen_action() {
  clone_ingress_pkt_to_egress(md.ing_mir_ses);
}

table pkt_gen_table {
  actions {
    pkt_gen_action;
  }
 default_action: pkt_gen_action;
}

/*---------- set_mark_1_t ----------*/
action set_mark_1_action() {
    modify_field(fabric.dstDevice, 55);
}

table set_mark_1_t {
  actions {
    set_mark_1_action;
  }
 default_action: set_mark_1_action;
}

/*---------- set_mark_2_t ----------*/
action set_mark_2_action() {
    modify_field(fabric.dstDevice, 60);
}

table set_mark_2_t {
  actions {
    set_mark_2_action;
  }
 default_action: set_mark_2_action;
}
